#include "./include/network.h"

int udp_server_init(struct networkindex *networkindex_obj)
{
	int ret;
	pthread_t tid1, tid2, tid3;
	struct sockaddr_in udp_bindaddr;

	udp_bindaddr.sin_family = AF_INET;
	udp_bindaddr.sin_port = htons(LOCAL_PORT);
	inet_pton(AF_INET, LOCAL_IP, &udp_bindaddr.sin_addr.s_addr);
	bzero(udp_bindaddr.sin_zero, sizeof(udp_bindaddr.sin_zero));

	pthread_mutex_init(&networkindex_obj->rl_mutex, NULL);
	pthread_mutex_init(&networkindex_obj->rl_mutex, NULL);

	networkindex_obj->udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
	
	ret = bind(networkindex_obj->udp_socket, (struct sockaddr *)&udp_bindaddr, sizeof(struct sockaddr_in));
	if(0 != ret)
	{
		return -1;
	}
	ret = pthread_create(&tid1, NULL, pthread_udp_recv, networkindex_obj);
	if(0 != ret)
	{
		return -1;
	}
	ret = pthread_detach(tid1);
	if(0 != ret)
	{
		return -1;
	}
	ret = pthread_create(&tid2, NULL, pthread_udp_send, networkindex_obj);
	if(0 != ret)
	{
		return -1;
	}
	ret = pthread_detach(tid2);
	if(0 != ret)
	{
		return -1;
	}
	ret = pthread_create(&tid3, NULL, pthread_recvlist_operation, networkindex_obj);
	if(0 != ret)
	{
		return -1;
	}
	ret = pthread_detach(tid3);
	if(0 != ret)
	{
		return -1;
	}
	return 0;
}

void recvlist_add(struct pointlist *rl_head, char *buffer, size_t buffer_size, struct sockaddr_in *recvaddr)
{
	struct recvlist *rl_tail = NULL;
	struct recvlist *rl_new = NULL;
	rl_new = (struct recvlist *)calloc(1, sizeof(struct recvlist));
	if(POINTLIST_IS_EMPTY(rl_head))
	{
		rl_new->recvid = 1;
	}
	else
	{
		rl_tail = POINTLIST_TO_ITEM(rl_head->prev, struct recvlist, pointer);
		rl_new->recvid = rl_tail->recvid + 1;
	}
	memcpy(&rl_new->recvaddr, recvaddr, sizeof(struct sockaddr_in));
	memcpy(rl_new->data, buffer, buffer_size);
	rl_new->flag = sizeof(struct recvlist);
	pointlist_add_tail(rl_head, &rl_new->pointer);
}

int recvlist_getfrist(struct pointlist *rl_head, struct recvlist **rl_tmp)
{
	if(POINTLIST_IS_EMPTY(rl_head))
	{
		return -1;
	}
	else
	{
		*rl_tmp = POINTLIST_TO_ITEM(rl_head->next, struct recvlist, pointer);
		return 0;
	}
}

void recvlist_show_foreach(struct pointlist *rl_head)
{
	struct pointlist *pl_tmp = NULL;
	struct recvlist *rl_tmp = NULL;
	
	POINTLIST_FOR_EACH(pl_tmp, rl_head)
	{
		rl_tmp = POINTLIST_TO_ITEM(pl_tmp, struct recvlist, pointer);
		recvlist_show(rl_tmp);
	}
}

void recvlist_show(struct recvlist *rl_tmp)
{
	printf("%02d ", rl_tmp->recvid);
	printf("%s:%d\t", inet_ntoa(rl_tmp->recvaddr.sin_addr), ntohs(rl_tmp->recvaddr.sin_port));
	printf("%s", rl_tmp->data);
	printf("\n");
}

void recvlist_del(struct pointlist *pl_tmp)
{
	struct recvlist *rl_tmp = NULL;
	pointlist_del(pl_tmp->prev, pl_tmp->next);
	pl_tmp->prev = NULL;
	pl_tmp->next = NULL;
	
	rl_tmp = POINTLIST_TO_ITEM(pl_tmp, struct recvlist, pointer);
	memset(rl_tmp, 0, sizeof(struct recvlist));
	free(rl_tmp);
}

void sendlist_add(struct pointlist *sl_head, char *buffer, size_t buffer_size, struct sockaddr_in *sendaddr)
{
	struct sendlist *sl_tail = NULL;
	struct sendlist *sl_new = NULL;
	sl_new = (struct sendlist *)calloc(1, sizeof(struct sendlist));
	if(POINTLIST_IS_EMPTY(sl_head))
	{
		sl_new->sendid = 1;
	}
	else
	{
		sl_tail = POINTLIST_TO_ITEM(sl_head->prev, struct sendlist, pointer);
		sl_new->sendid = sl_tail->sendid + 1;
	}
	memcpy(&sl_new->sendaddr, sendaddr, sizeof(struct sockaddr_in));
	memcpy(sl_new->data, buffer, buffer_size);
	sl_new->flag = sizeof(struct sendlist);
	pointlist_add_tail(sl_head, &sl_new->pointer);
}

int sendlist_getfrist(struct pointlist *sl_head, struct sendlist **sl_tmp)
{
	if(POINTLIST_IS_EMPTY(sl_head))
	{
		return -1;
	}
	else
	{
		*sl_tmp = POINTLIST_TO_ITEM(sl_head->next, struct sendlist, pointer);
		return 0;
	}
}

void sendlist_show_foreach(struct pointlist *sl_head)
{
	struct pointlist *pl_tmp = NULL;
	struct sendlist *sl_tmp = NULL;
	
	POINTLIST_FOR_EACH(pl_tmp, sl_head)
	{
		sl_tmp = POINTLIST_TO_ITEM(pl_tmp, struct sendlist, pointer);
		sendlist_show(sl_tmp);
	}
}

void sendlist_show(struct sendlist *sl_tmp)
{
	printf("%02d ", sl_tmp->sendid);
	printf("%s\t", sl_tmp->data);
	printf("\n");
}

void sendlist_del(struct pointlist *pl_tmp)
{
	struct sendlist *sl_tmp = NULL;
	pointlist_del(pl_tmp->prev, pl_tmp->next);
	pl_tmp->prev = NULL;
	pl_tmp->next = NULL;
	
	sl_tmp = POINTLIST_TO_ITEM(pl_tmp, struct sendlist, pointer);
	memset(sl_tmp, 0, sizeof(struct sendlist));
	free(sl_tmp);
}